/**
 * @name: mapMethods.js
 * @author: XU>.<CHEN
 * @date: 2023-05-15 09:34
 * @description：mapMethods.js
 * @update: 2023-05-15 09:34
 */

import mapboxgl from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css';
import * as turf from '@turf/turf'
import china from './china'
import airplane from '@/assets/images/bubbleMap/airplane.png'
import chinaJson from '@/assets/jsonForMap/china.json'


mapboxgl.accessToken = 'pk.eyJ1IjoiYmxhY2tzaWRldiIsImEiOiJjbGdvc2w1amYwOTE2M3FtdnlxNjY2dXByIn0.BANXu8ULNbVU4xdBqwsFlQ'
// mapboxgl.setRTLTextPlugin("https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.1.0/mapbox-gl-rtl-text.js");

/**
 * @description: 基础地图配置
 */
export function createMap(dom: any) {
  const map = new mapboxgl.Map({
    container: dom,
    style: 'mapbox://styles/blacksidev/clc5xxx2b004814k8ytvkmf7r?optimize=true',
    // style: "mapbox://styles/mapbox/streets-v11?optimize=true",
    // style: (china as any), // 离线化部署
    // style: test, // 离线化部署
    center: [105.7350860781, 38.3459367715], // 初始坐标系：北京市
    zoom: 3, //  当前显示地图级别
    minZoom: 2, // 最小显示地图级别
    maxZoom: 21, // 最大显示地图级别
    testMode: true, // 将由于无效的 accessToken 而生成的错误和警告静音
    pitch: 0,  //地图的角度，不写默认是0，取值是0-60度，一般在3D中使用
    bearing: 0, //地图的初始方向，值是北的逆时针度数，默认是0，即是正北
    antialias: false, //抗锯齿，通过false关闭提升性能
    preserveDrawingBuffer: true, // 因为html2canvas 不读取canvas标签中的内容,不加的话导出地图是空的
    pitchWithRotate: false, // 俯仰（倾斜）控制与“拖动旋转”交互将被禁用。
  })
  const navigation = new mapboxgl.NavigationControl()
  map.addControl(navigation, 'top-left'); // 导航条
  // map.addControl(new MapboxLanguage({ defaultLanguage: 'zh-Hans' })); // 中文
  return {
    map,
    navigation
  }
}

// 设置迁徙图基础数据
export function setMigrationMapData(linesMaps: number[][], pointGroups: point[], route: resultItem, point: resultItem, steps: number, counter: number) {
  linesMaps.forEach(item => {
    const origin: number[] = pointGroups.find(e => e.adcode === item[0])?.coordinates || []
    const destination: number[] = pointGroups.find(e => e.adcode === item[1])?.coordinates || []
    route.features.push({
      'type': 'Feature',
      'properties': {},
      'geometry': {
        'type': 'LineString',
        'coordinates': [origin, destination]
      }
    })
    // 轨迹点
    point.features.push({
      'type': 'Feature',
      'properties': {},
      'geometry': {
        'type': 'Point',
        'coordinates': origin
      }
    })
  })

  // 计算路线起点/终点之间的距离（以公里为单位）
  route.features.map(feature => {
    const lineDistance = turf.length(feature)
    const arc = []
    // 在两点的“起点”和“目的地”之间画一条弧线
    for (let i = 0; i < lineDistance; i += lineDistance / steps) {
      const segment = turf.along(feature, i);
      arc.push(segment.geometry.coordinates);
    }
    // 使用计算出的弧坐标更新路径
    feature.geometry.coordinates = arc;
  })
  // 用于根据路径递增点测量值
  counter = 0;
}

// 加载气泡图标文件
export function loadBubbleImg(map: any, imgList: string[]) {
  imgList.forEach(img => {
    map.loadImage('airplane', (error: any, image: any) => {
      map.addImage(img, image, {
        "sdf": true
      })
    })
  })
}

// 构造端点的 GEOJSON 数据
export function buildMigrationData(linesMaps: number[][], pointGroups: point[]): migrationData {
  let origins: number[] = []// 起点集合
  let destinations: number[] = []// 终点集合
  linesMaps.forEach((item: number[]) => {
    if (!origins.find(e => e === item[0])) origins.push(item[0])
    if (!destinations.find(e => e === item[1])) destinations.push(item[1])
  })
  const result: { origin: resultItem, destination: resultItem } = {
    origin: {'type': 'FeatureCollection', 'features': []},
    destination: {'type': 'FeatureCollection', 'features': []}
  }
  const feature = (item: point): feature => {
    return {
      "type": "Feature",
      "properties": {
        "id": item.adcode,
        "name": item.name,
        "cp": item.coordinates,
        "showHover": true,
        "fields": []
      },
      "geometry": {
        "type": "Point",
        "coordinates": item.coordinates
      }
    }
  }

  origins.map(adcode => {
    const item: (point | undefined) = pointGroups.find(e => e.adcode === adcode)
    if (item) result.origin.features.push(feature(item))
  })
  destinations.map(adcode => {
    const item: (point | undefined) = pointGroups.find(e => e.adcode === adcode)
    if (item)  result.destination.features.push(feature(item))
  })
  return result
}

export function buildFillData(pointGroups: point[]): resultItem {
  // const result = { 'type': 'FeatureCollection', 'features': [] }
  // result.
  return chinaJson
}

// 飞线动画
export function animate(counter: number, counterKey:number, l_map: any, l_index: number, steps: number, route: resultItem, point: resultItem, linesMaps: number[][], pointGroups: point[]) {
  if (!l_map) return
  let timeHandle = null
  clearTimeout(timeHandle)

  animateFrame()

  function animateFrame() {
    // 当迁徙图标及动画设置处于开启状态时再请求下一帧以提高性能
    // if (!_this.migrationStyle.animate || !_this.migrationStyle.iconShow) {
    //   counter = 0
    //   return
    // }

    const start = route.features[l_index].geometry.coordinates[counter >= steps ? counter - 1 : counter];
    const end = route.features[l_index].geometry.coordinates[counter >= steps ? counter : counter + 1 ];
    if (!start || !end) return;
    // 根据计数器表示将点几何更新到新位置
    point.features[l_index].geometry.coordinates = route.features[l_index].geometry.coordinates[counter];
    // 计算方位角以确保图标旋转以匹配路线弧方位角
    point.features[l_index].properties.bearing = turf.bearing(turf.point(start), turf.point(end));
    // 使用此新数据更新源
    l_map.getSource('point').setData(point);
    // 请求下一帧动画，只要尚未到达结束 counterKey === _this.counterKey 避免重复动画
    if (counter < steps && `${counterKey}${l_index}` === `${counterKey}${l_index}`) {requestAnimationFrame(animateFrame);}
    counter = counter + 1;
    if (counter === steps - 1) {
      const originByLIndex = pointGroups.find(e => e.adcode === linesMaps[l_index][0])
      point.features[l_index].geometry.coordinates = originByLIndex.coordinates;
      l_map.getSource('point').setData(point);
      counter = 0;
    }
  }

  // 定时暂停动画
  timeHandle = setTimeout(() => {
    counter = steps
  }, 1000 * 60)
}